package com.totcy.atom.net;

import android.content.Context;
import android.support.annotation.NonNull;

import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.orhanobut.logger.Logger;
import com.totcy.atom.CommonValues;
import com.totcy.atom.bean.response.HttpResponse;
import com.totcy.atom.net.api.ApiService;
import com.totcy.atom.net.exception.ApiException;
import com.totcy.atom.net.interceptor.CustomInterceptor;
import com.totcy.baselibrary.utils.LogUtils;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.fastjson.FastJsonConverterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * description: 网络请求管理类
 * author: Totcy
 * date: 2017/9/19 10:55
 * update: 2017/9/19
 */

public class HttpManager {
    private static final int DEFAULT_TIMEOUT = 10;
    private static ApiService mApiService;

    public static ApiService getApiService(@NonNull Context context) {
        if (mApiService == null) {
            synchronized (HttpManager.class) {
                if (mApiService == null) {
                    OkHttpClient.Builder builder = new OkHttpClient.Builder();
                    builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
                    builder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
                    builder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
                    //拦截添加headers
                    builder.addInterceptor(new CustomInterceptor(context));
                    if (CommonValues.isRunningTest) {
                        //请求log打印
                        builder.addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                            @Override
                            public void log(String message) {
                                LogUtils.logi(message);
                            }
                        }).setLevel(HttpLoggingInterceptor.Level.BODY));
                    }
                    OkHttpClient client = builder.build();

                    Retrofit retrofit = new Retrofit.Builder()
                            .baseUrl(CommonValues.SERVER_URL)
                            .client(client)
                            //.addConverterFactory(GsonConverterFactory.create())
                            .addConverterFactory(FastJsonConverterFactory.create())
                            //关联RxJava2
                            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                            .build();
                    mApiService = retrofit.create(ApiService.class);
                }
            }
        }
        return mApiService;
    }

    /**
     * 重用 使用一个单例 ObservableTransformer 线程切换
     */
    static final ObservableTransformer schedulersTransformer = new ObservableTransformer() {
        @Override
        public ObservableSource apply(Observable upstream) {
            return upstream.subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread());
        }
    };

    /**
     * Rx线程调度切换
     *
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> ObservableTransformer<HttpResponse<T>, HttpResponse<T>> applySchedulers() {
        return (ObservableTransformer<HttpResponse<T>, HttpResponse<T>>) schedulersTransformer;
    }

    /**
     * Rx优雅处理服务器返回,成功返回T实体，失败抛出异常（服务器返回的code和message）
     *
     * @param <T>
     * @return
     */
    public static <T> ObservableTransformer<HttpResponse<T>, T> handleResult() {
        return new ObservableTransformer<HttpResponse<T>, T>() {
            @Override
            public ObservableSource<T> apply(Observable<HttpResponse<T>> upstream) {
                return upstream.map(new Function<HttpResponse<T>, T>() {
                    @Override
                    public T apply(@NonNull HttpResponse<T> response) throws Exception {
                        if (response.isSuccessful()) {
                            //not null throw "The mapper function returned a null value."
                            return response.getData();
                        } else {
                            throw new ApiException(response.getCode(), response.getMessage());
                        }
                    }
                });
            }
        };
    }

}
